home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / DesktopDoubler / NubApp / Main.cc < prev    next >
C/C++ Source or Header  |  1999-06-25  |  6KB  |  311 lines

  1. #define DISABLE_LOCAL_CALLTRACE        1        // Set to 1 to disable Call Traces for this file.
  2. #define DISABLE_LOCAL_DEBUG            0        // Set to 1 to disable all debugging for this file.
  3. #include "DebugUtils.h"
  4.  
  5. #include <Appearance.h>
  6. #include <Dialogs.h>
  7. #include <Fonts.h>
  8. #include <Gestalt.h>
  9. #include <LowMem.h>
  10. #include <Resources.h>
  11. #include <stdio.h>
  12. #include <TextEdit.h>
  13. #include <Traps.h>
  14. #include "Event.h"
  15. #include "ContextUtils.h"
  16. #include "Main.h"
  17. #include "Menu.h"
  18. #include "MetroNubUtils.h"
  19. #include "Notice.h"
  20. #include "Nub.h"
  21. #include "Window.h"
  22.  
  23.  
  24.  
  25.  
  26. typedef pascal void (*ExitToShellProcPtr)(void);
  27.  
  28. enum
  29. {
  30.     uppExitToShellProcInfo = kPascalStackBased
  31. };
  32.  
  33. #if GENERATINGCFM
  34. typedef UniversalProcPtr ExitToShellUPP;
  35. #define NewExitToShellProc(userRoutine)            \
  36.         (ExitToShellUPP)NewRoutineDescriptor((ProcPtr)(userRoutine),uppExitToShellProcInfo,GetCurrentArchitecture())
  37. #define CallExitToShellProc(userRoutine)        \
  38.         CallUniversalProc((UniversalProcPtr)(userRoutine),uppExitToShellProcInfo)
  39. #else
  40. typedef ExitToShellProcPtr ExitToShellUPP;
  41. #define NewExitToShellProc(userRoutine)            ((ExitToShellUPP)(userRoutine))
  42. #define CallExitToShellProc(userRoutine)        (*(((ExitToShellUPP)userRoutine)))()
  43. #endif
  44.  
  45.  
  46. #ifdef __cplusplus
  47. extern "C" {
  48. #endif
  49.  
  50. extern OSStatus NubMain(Handle code);
  51. static void Initialize(void);
  52. static void CleanUp(void);
  53. static void MainEventLoop(void);
  54. static pascal void ExitToShellPatch(void);
  55.  
  56. #ifdef __cplusplus
  57. }
  58. #endif
  59.  
  60.  
  61. #if GENERATINGCFM
  62.     static RoutineDescriptor                gExitToShellPatchRD = BUILD_ROUTINE_DESCRIPTOR(uppExitToShellProcInfo,ExitToShellPatch);
  63.     static ExitToShellUPP                    gExitToShellPatchUPP = (ExitToShellUPP)&gExitToShellPatchRD;
  64.     static ExitToShellUPP                    gExitToShellUPP;
  65. #elif __A5__
  66.     static ExitToShellUPP                    gExitToShellPatchUPP = ExitToShellPatch;
  67.     static ExitToShellUPP                    gExitToShellUPP;
  68. #endif
  69.  
  70.  
  71. Boolean                                        gExitToShellHasBeenCalled = false;
  72. Boolean                                        gWeAreBeingDebugged = false;
  73.  
  74. EventManager                                *gEventManager = NULL;
  75. MenuManager                                    *gMenuManager = NULL;
  76. WindowManager                                *gWindowManager = NULL;
  77. Boolean                                        gExitFlag = false;
  78.  
  79. FileMenu                                    *gFileMenu = NULL;
  80.  
  81.  
  82.  
  83.  
  84.  
  85. void main(void)
  86. {
  87.     NubInfo        *info = NULL;
  88.     Handle        code = NULL;
  89.     OSStatus    err;
  90.     
  91.     
  92.     Initialize();
  93.     
  94.     // Get NubInfo from Gestalt.
  95.     err = Gestalt(kNubSelector,(long*)&info);
  96.     if (err != noErr)
  97.         info = NULL;
  98.     
  99.     // Check for prior existence of the Nub.
  100.     if ((err != noErr) || (info == NULL))
  101.     {
  102.         PostNotice(kAlertStopAlert,"\pNub is not installed!","\pThis app requires that " \
  103.                 "\pthe Nub be installed at startup to load the required system patches.");
  104.         ExitToShell();
  105.     }
  106.     
  107.     // Check if the Nub is currently loaded.
  108.     if (info->signature == kNubSignature)
  109.     {
  110.         if (info->unloadProc == NULL)
  111.         {
  112.             PostNotice(kAlertStopAlert,"\pNub couldn't be unloaded!","\pNub " \
  113.                         "\pappears to be loaded, but there isn't a registered unload procedure.");
  114.             ExitToShell();
  115.         }
  116.         
  117.         // Unload Nub.
  118.         {
  119.             THzContext    zone(SystemZone());
  120.             
  121.             err = CallNubUnloadProc(info->unloadProc,&code);
  122.             if (err != noErr)
  123.             {
  124.                 Str255    msg;
  125.                 
  126.                 msg[0] = sprintf((char*)&msg[1],"The Nub unload procedure failed: %ld",err);
  127.                 PostNotice(kAlertStopAlert,"\pNub couldn't be unloaded!",msg);
  128.                 ExitToShell();
  129.             }
  130.         }
  131.         
  132.         if (code != NULL)
  133.             DisposeHandle(code);
  134.     }
  135.     
  136.     // Load app-based Nub.
  137.     {
  138.         THzContext    zone(SystemZone());
  139.         
  140.         err = NubMain(NULL);
  141.         if (err != noErr)
  142.         {
  143.             Str255    msg;
  144.             
  145.             msg[0] = sprintf((char*)&msg[1],"The Nub load procedure failed: %ld",err);
  146.             PostNotice(kAlertStopAlert,"\pNub couldn't be loaded!",msg);
  147.             ExitToShell();
  148.         }
  149.     }
  150.     
  151.     // Patch ExitToShell so we can guarantee our clean up.
  152.     gExitToShellUPP = (ExitToShellUPP)NGetTrapAddress(_ExitToShell,ToolTrap);
  153.     NSetTrapAddress((UniversalProcPtr)gExitToShellPatchUPP,_ExitToShell,ToolTrap);
  154.         
  155.     MainEventLoop();
  156. }
  157.  
  158.  
  159.  
  160.  
  161.  
  162. void Initialize(void)
  163. {
  164.     SInt32        result;
  165.     OSStatus    err;
  166.     
  167.     
  168.     // Expand our heap to is maximum, this
  169.     // will help keep fragmentation low, etc.
  170.     MaxApplZone();
  171.     
  172.     // Init toolbox.
  173.     InitGraf(&qd.thePort);
  174.     InitFonts();
  175.     InitWindows();
  176.     InitMenus();
  177.     InitCursor();
  178.     TEInit();
  179.     FlushEvents(everyEvent,0);
  180.     InitDialogs(NULL);
  181.     
  182.     // Check for Appearance Manager.
  183.     err = Gestalt('appr',&result);
  184.     if ((err == noErr) && (result & 1))
  185.         RegisterAppearanceClient();
  186.     
  187.     // Check for high-level debugger.
  188.     if (AmIBeingMWDebugged())
  189.         gWeAreBeingDebugged = true;
  190.         
  191.     InitAppleEvents();
  192.     
  193.     gEventManager = new BaseEventManager;
  194.     gMenuManager = new BaseMenuManager;
  195.     gWindowManager = new BaseWindowManager;
  196.     
  197.     new AppleMenu;
  198.     gFileMenu = new FileMenu;
  199.     new EditMenu;
  200.     
  201.     DrawMenuBar();
  202. }
  203.  
  204.  
  205.  
  206.  
  207.  
  208. void CleanUp(void)
  209. {
  210.     NubInfo        *info = NULL;
  211.     Handle        code = NULL;
  212.     OSStatus    err;
  213.     
  214.     
  215.     // Get NubInfo from Gestalt.
  216.     err = Gestalt(kNubSelector,(long*)&info);
  217.     if (err != noErr)
  218.         info = NULL;
  219.     
  220.     // Check for current existence of the Nub.
  221.     if ((err != noErr) || (info == NULL))
  222.     {
  223.         PostNotice(kAlertStopAlert,"\pNub is not installed!","\pNub was installed when I launched "\
  224.                 "\pso I don't know why your seeing this now, there is a very good chance that your going crash!");
  225.         return;
  226.     }
  227.     
  228.     // Check if Nub is currently loaded.
  229.     if (info->signature == kNubSignature)
  230.     {
  231.         if (info->unloadProc == NULL)
  232.         {
  233.             PostNotice(kAlertStopAlert,"\pNub couldn't be unloaded!","\pNub didn't register an unload " \
  234.                     "\pprocedure, however since we loaded successfully there is a very good chance that your going crash!");
  235.             return;
  236.         }
  237.         
  238.         // Unload Nub.
  239.         {
  240.             THzContext    zone(SystemZone());
  241.             
  242.             err = CallNubUnloadProc(info->unloadProc,&code);
  243.             if (err != noErr)
  244.             {
  245.                 Str255    msg;
  246.                 
  247.                 msg[0] = sprintf((char*)&msg[1],"The Nub unload procedure failed: %ld, there is a " \
  248.                                 "very good chance that your going crash!",err);
  249.                 PostNotice(kAlertStopAlert,"\pNub couldn't be unloaded!",msg);
  250.                 return;
  251.             }
  252.         }
  253.         
  254.         if (code != NULL)
  255.             DisposeHandle(code);
  256.     }
  257. }
  258.  
  259.  
  260.  
  261.  
  262.  
  263. void SubEventLoop(short eventMask,UInt32 sleepTime)
  264. {
  265.     EventRecord    event;
  266.     Boolean        result;
  267.     
  268.     
  269.     result = WaitNextEvent(eventMask,&event,sleepTime,NULL);
  270.     gEventManager->DoDispatch(&event);
  271. }
  272.  
  273.  
  274.  
  275.  
  276.  
  277. void MainEventLoop(void)
  278. {
  279.     gExitFlag = false;
  280.     while(!gExitFlag)
  281.         SubEventLoop(everyEvent,60L);
  282. }
  283.  
  284.  
  285.  
  286.  
  287.  
  288. pascal void ExitToShellPatch(void)
  289. {
  290.     #if __A5__
  291.         SetCurrentA5();
  292.     #endif
  293.     
  294.     if (!gExitToShellHasBeenCalled)
  295.     {
  296.         gExitToShellHasBeenCalled = true;
  297.         CleanUp();
  298.     }
  299.     
  300.     CallExitToShellProc(gExitToShellUPP);
  301. }
  302.  
  303.  
  304.  
  305.  
  306.  
  307. void InitiateAppQuit(void)
  308. {
  309.     gExitFlag = true;
  310. }
  311.